home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / wnos / wn941101 / iface.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-30  |  12.1 KB  |  502 lines

  1. #include <stdio.h>
  2. #include "global.h"
  3. #include "config.h"
  4. #include "mbuf.h"
  5. #include "proc.h"
  6. #include "iface.h"
  7. #include "ip.h"
  8. #include "netuser.h"
  9. #include "ax25.h"
  10. #include "enet.h"
  11. #include "pktdrvr.h"
  12. #include "cmdparse.h"
  13. #include "commands.h"
  14. #ifdef CRCSET
  15. #include "crc.h"
  16. static int ifcrc __ARGS((int argc,char *argv[],void *p));
  17. #endif
  18.  
  19. /* Loopback pseudo-interface */
  20. struct iface Loopback = {
  21.     &Encap,            /* Link to next entry */
  22.     "loopback",        /* name        */
  23.     CL_NONE,        /* type        */
  24.     &Iftypes[0],        /* iftype    */
  25.     0x7f000001L,        /* addr        127.0.0.1 */
  26.     0xffffffffL,        /* broadcast    255.255.255.255 */
  27.     0xffffffffL,        /* netmask    255.255.255.255 */
  28.     NULL,            /* (*ioctl)    */
  29.     NULLFP,            /* (*iostatus)    */
  30.     NULLFP,            /* (*send)    */
  31.     NULLFP,            /* (*output)    */
  32.     NULLFP,            /* (*raw)    */
  33.     NULLFP,            /* (*stop)    */
  34.     NULLFP,            /* (*status)    */
  35.     MAXINT16,        /* mtu    No limit */
  36.     0,            /* dev        */
  37.     0,            /* xdev        */
  38.     0,            /* port     */
  39. /*    0,            /* flags    */
  40.     0,            /* trace    */
  41.     NULLCHAR,        /* trfile    */
  42.     NULLFILE,        /* trfp        */
  43.     NULLCHAR,        /* hwaddr    */
  44.     NULLIF,            /* forw        */
  45.     0,            /* ipsndcnt    */
  46.     0,            /* rawsndcnt    */
  47.     0,            /* iprcvcnt    */
  48.     0,            /* rawrcvcnt    */
  49.     0,            /* lastsent    */
  50.     0,            /* lastrecv    */
  51.     NULLPROC,        /* rxproc    */
  52.     NULLPROC,        /* txproc    */
  53.     NULLPROC,        /* supv        */
  54. #ifdef CRCSET
  55.         0,                      /* sendcrc      */
  56.         0,                      /* crcerrors    */
  57. #endif
  58.     NULL,            /* extension    */
  59.     0,
  60.     NULLLQ,
  61.     MAXDEFAULT,
  62.     0,
  63. };
  64.  
  65. /* Encapsulation pseudo-interface */
  66. struct iface Encap = {
  67.     NULLIF,
  68.     "encap",        /* name        */
  69.     CL_NONE,        /* type        */
  70.     &Iftypes[0],        /* iftype    */
  71.     INADDR_ANY,        /* addr        0.0.0.0 */
  72.     0xffffffffL,        /* broadcast    255.255.255.255 */
  73.     0xffffffffL,        /* netmask    255.255.255.255 */
  74.     NULL,            /* (*ioctl)    */
  75.     NULLFP,            /* (*iostatus)    */
  76.     ip_encap,        /* (*send)    */
  77.     NULLFP,            /* (*output)    */
  78.     NULLFP,            /* (*raw)    */
  79.     NULLFP,            /* (*stop)    */
  80.     NULLFP,            /* (*status)    */
  81.     MAXINT16,        /* mtu        No limit */
  82.     0,            /* dev        */
  83.     0,            /* xdev        */
  84.     0,            /* port        */
  85. /*    0,            /* flags    */
  86.     0,            /* trace    */
  87.     NULLCHAR,        /* trfile    */
  88.     NULLFILE,        /* trfp        */
  89.     NULLCHAR,        /* hwaddr    */
  90.     NULLIF,            /* forw        */
  91.     0,            /* ipsndcnt    */
  92.     0,            /* rawsndcnt    */
  93.     0,            /* iprcvcnt    */
  94.     0,            /* rawrcvcnt    */
  95.     0,            /* lastsent    */
  96.     0,            /* lastrecv    */
  97.     NULLPROC,        /* rxproc    */
  98.     NULLPROC,        /* txproc    */
  99.     NULLPROC,        /* supv        */
  100. #ifdef CRCSET
  101.         0,                      /* sendcrc      */
  102.         0,                      /* crcerrors    */
  103. #endif
  104.     NULL,            /* extension    */
  105.     0,
  106.     NULLLQ,
  107.     MAXDEFAULT,
  108.     0,
  109. };
  110.  
  111. /* Interface list header */
  112. struct iface *Ifaces = &Loopback;
  113.  
  114. char Badif[]     = "Interface %s unknown\n";
  115. char Badax[]     = "Interface %s not AX25\n";
  116. char Noipaddr[] = "IP adress not set\n";
  117. char Ifexist[]    = "Interface %s already exists\n";
  118.  
  119. static int near mask2width __ARGS((int32 mask));
  120. static void showiface __ARGS((struct iface *ifp));
  121.  
  122. #ifdef AX25
  123. void
  124. init_flags(struct iface *ifp)
  125. {
  126.   ifp->flags = mxallocw(sizeof(struct flags));
  127.   ifp->flags->maxframe = Maxframe;
  128.   ifp->flags->t1init = T1init;
  129.   ifp->flags->t2init = T2init;
  130.   ifp->flags->t3init = T3init;
  131.   ifp->flags->t4init = T4init;
  132.   ifp->flags->t5init = T5init;
  133.   ifp->flags->t6init = T6init;        /* DAMA timeout */
  134.   ifp->flags->retries = Retries;
  135.   ifp->flags->axwindow = Axwindow;
  136.   ifp->flags->paclen = Paclen;
  137.   ifp->flags->pthresh = Pthresh;
  138.   ifp->flags->digipeat = Digipeat;
  139.   ifp->flags->t3disc = T3disc;
  140.   ifp->flags->dama_slave = 0;        /* DAMA slave flag */
  141.   ifp->flags->dama_busy = 0;        /* wait until poll */
  142. }
  143. #endif
  144.  
  145. /* Given a network mask, return the number of contiguous 1-bits starting
  146.  * from the most significant bit.
  147.  */
  148. static int near
  149. mask2width(int32 mask)
  150. {
  151.   int i, width = 0;
  152.  
  153.   for(i = 31;i >= 0;i--) {
  154.     if(!(mask & (1L << i)))
  155.       break;
  156.     width++;
  157.   }
  158.   return width;
  159. }
  160.  
  161. /* Set interface IP address */
  162. static int
  163. ifipaddr(int argc,char *argv[],void *p)
  164. {
  165.   struct iface *ifp = p;
  166.  
  167.   if((ifp->addr = resolve(argv[1])) == 0) {
  168.     tprintf(Badhost,argv[1]);
  169.     return -1;
  170.   }
  171.   return 0;
  172. }
  173.  
  174. /* Set link (hardware) address */
  175. static int
  176. iflinkadr(int argc,char *argv[],void *p) {
  177.   struct iface *ifp = p;
  178.  
  179.   if(ifp->iftype == NULLIFT || ifp->iftype->scan == NULL){
  180.     tputs("Can't set link address\n");
  181.     return -1;
  182.   }
  183.   if(ifp->hwaddr != NULLCHAR)
  184.     xfree(ifp->hwaddr);
  185.   ifp->hwaddr = mxallocw(ifp->iftype->hwalen);
  186.   if(*ifp->iftype->scan != 0)
  187.     return (*ifp->iftype->scan)(ifp->hwaddr,argv[1]);
  188.   return 0;
  189. }
  190.  
  191. /* Set interface broadcast address. This is actually done
  192.  * by installing a private entry in the routing table.
  193.  */
  194. static int
  195. ifbroad(int argc,char *argv[],void *p) {
  196.   struct iface *ifp = p;
  197.   struct route *rp;
  198.  
  199.   if((rp = rt_blookup(ifp->broadcast,32)) != NULLROUTE && rp->iface == ifp)
  200.     rt_drop(ifp->broadcast,32);
  201.   if((ifp->broadcast = resolve(argv[1])) == 0) {
  202.     tprintf(Badhost,argv[1]);
  203.     return -1;
  204.   }
  205.   rt_add(ifp->broadcast,32,0L,ifp,1L,0L,1);
  206.   return 0;
  207. }
  208.  
  209. static int
  210. ifname(int argc,char *argv[],void *p) {
  211.   struct iface *ifp = p;
  212.  
  213.   if(ifp->name != NULLCHAR)
  214.     xfree(ifp->name);
  215.   ifp->name = strxdup(argv[1]);
  216.   return 0;
  217. }
  218.  
  219. /* Set the network mask. This is actually done by installing
  220.  * a routing entry.
  221.  */
  222. static int
  223. ifnetmsk(int argc,char *argv[],void *p) {
  224.   struct iface *ifp = p;
  225.   struct route *rp;
  226.  
  227.   /* Remove old entry if it exists */
  228.   if((rp = rt_blookup(ifp->addr & ifp->netmask,mask2width(ifp->netmask))) != NULLROUTE)
  229.     rt_drop(rp->target,rp->bits);
  230.   ifp->netmask = htol(argv[1]);
  231.   rt_add(ifp->addr,mask2width(ifp->netmask),0L,ifp,0L,0L,0);
  232.   return 0;
  233. }
  234.  
  235. /* Command to set interface encapsulation mode */
  236. static int
  237. ifencap(int argc,char *argv[],void *p) {
  238.   struct iface *ifp = p;
  239.  
  240.   if(setencap(ifp,argv[1]) != 0) {
  241.     tprintf("Encap mode %s unknown\n",argv[1]);
  242.     return 1;
  243.   }
  244.   return 0;
  245. }
  246. /* Function to set encapsulation mode */
  247. int
  248. setencap(struct iface *ifp,char *mode) {
  249.   struct iftype *ift;
  250.  
  251.   for(ift = &Iftypes[0];ift->name != NULLCHAR;ift++)
  252.       if(strnicmp(ift->name,mode,strlen(mode)) == 0)
  253.           break;
  254.   if(ift->name == NULLCHAR)
  255.       return -1;
  256.   ifp->iftype = ift;
  257.   ifp->send = ift->send;
  258.   ifp->output = ift->output;
  259.   ifp->type = ift->type;
  260.   return 0;
  261. }
  262.  
  263. /* Set interface Maximum Transmission Unit */
  264. static int
  265. ifmtu(int argc,char *argv[],void *p)
  266. {
  267.   struct iface *ifp = p;
  268.  
  269.   ifp->mtu = atoi(argv[1]);
  270.   return 0;
  271. }
  272.  
  273. /* Set interface forwarding */
  274. static int
  275. ifforw(int argc,char *argv[],void *p) {
  276.   struct iface *ifp = p;
  277.  
  278.   if((ifp->forw = if_lookup(argv[1])) == NULLIF)
  279.     return -1;
  280.   if(ifp->forw == ifp)
  281.     ifp->forw = NULLIF;
  282.   return 0;
  283. }
  284. #ifdef CRCSET
  285.  
  286. static int
  287. ifcrc(argc,argv,p)
  288. int argc;
  289. char *argv[];
  290. void *p;
  291. {
  292.         struct iface *ifp = p;
  293.         return setbool(&ifp->sendcrc, "CRC generation",argc,argv);
  294. }
  295. #endif
  296.  
  297. /* Display the parameters for a specified interface */
  298. static void
  299. showiface(struct iface *ifp) {
  300.   char tmp[25];
  301.  
  302.   tprintf("%-10s IP addr %s MTU %u Link encap ",
  303.         ifp->name,inet_ntoa(ifp->addr),(int)ifp->mtu);
  304.   if(ifp->iftype == NULLIFT){
  305.     tputs("not set\n");
  306.   } else {
  307.     tprintf("%s\n",ifp->iftype->name);
  308.     if(ifp->iftype->format != NULL && ifp->hwaddr != NULLCHAR)
  309.       tprintf("%20s %s\n","Link addr",(*ifp->iftype->format)(tmp,ifp->hwaddr));
  310.   }
  311.   tprintf("%16s 0x%x netmask 0x%08lx\n","trace",ifp->trace,ifp->netmask);
  312.   tprintf("%19s %lu tot %lu idle %s\n",
  313.       "sent: ip",ifp->ipsndcnt,ifp->rawsndcnt,tformat(secclock() - ifp->lastsent));
  314.   tprintf("%19s %lu tot %lu idle %s\n",
  315.       "recv: ip",ifp->iprecvcnt,ifp->rawrecvcnt,tformat(secclock() - ifp->lastrecv));
  316.   if(ifp->forw != NULLIF)
  317.       tprintf("%28s %s\n","output forward to",ifp->forw->name);
  318.   if (ifp->flags) {
  319.     tprintf("%-10s DAMA slave o"," ");
  320.     if (ifp->flags->dama_slave)
  321.       tprintf("n with %u connection(s)\n",ifp->flags->dama_slave);
  322.     else
  323.       tputs("ff\n");
  324. #ifdef CRCSET
  325.     tprintf("           CRC %s errors %lu\n",
  326.     ifp->sendcrc ? "enabled" : "disabled",ifp->crcerrors);
  327. #endif
  328.   }
  329. }
  330.  
  331. /* Command to detach an interface */
  332. int
  333. dodetach(int argc,char *argv[],void *p) {
  334.   struct iface *ifp;
  335.  
  336.   if((ifp = if_lookup(argv[1])) == NULLIF){
  337.     tprintf(Badif,argv[1]);
  338.     return 1;
  339.   }
  340.   if(if_detach(ifp) == -1)
  341.     tputs("Can't detach loopback interface\n");
  342.   return 0;
  343. }
  344. /* Detach a specified interface */
  345. int
  346. if_detach(struct iface *ifp) {
  347.   struct iface *iftmp;
  348.   struct route *rp,*rptmp;
  349.   int i,j;
  350.  
  351.   if(ifp == &Loopback || ifp == &Encap)
  352.     return -1;
  353.  
  354.   /* Drop all routes that point to this interface */
  355.   if(R_default.iface == ifp)
  356.     rt_drop(0L,0);    /* Drop default route */
  357.  
  358.   for(i = 0; i < HASHMOD; i++) {
  359.     for(j = 0; j < 32; j++) {
  360.       for(rp = Routes[j][i];rp != NULLROUTE;rp = rptmp){
  361.     /* Save next pointer in case we delete this entry */
  362.     rptmp = rp->next;
  363.     if(rp->iface == ifp)
  364.       rt_drop(rp->target,rp->bits);
  365.       }
  366.     }
  367.   }
  368.   /* Unforward any other interfaces forwarding to this one */
  369.   for(iftmp = Ifaces;iftmp != NULLIF;iftmp = iftmp->next){
  370.     if(iftmp->forw == ifp)
  371.       iftmp->forw = NULLIF;
  372.   }
  373.  
  374.   /* Call device shutdown routine, if any */
  375.   if(ifp->stop != NULLFP)
  376.     (*ifp->stop)(ifp,0);
  377.  
  378.   killproc(ifp->proc);
  379.   killproc(ifp->proc1);
  380.   killproc(ifp->supv);
  381.  
  382.   /* Free allocated memory associated with this interface */
  383.   if(ifp->name != NULLCHAR)
  384.     xfree(ifp->name);
  385.   if(ifp->hwaddr != NULLCHAR)
  386.     xfree(ifp->hwaddr);
  387.  
  388.   /* Remove from interface list */
  389.   if(ifp == Ifaces){
  390.     Ifaces = ifp->next;
  391.   } else {
  392.     /* Search for entry just before this one
  393.     * (necessary because list is only singly-linked.)
  394.     */
  395.     for(iftmp = Ifaces;iftmp != NULLIF ;iftmp = iftmp->next)
  396.       if(iftmp->next == ifp)
  397.     break;
  398.       if(iftmp != NULLIF && iftmp->next == ifp)
  399.     iftmp->next = ifp->next;
  400.   }
  401.   if(ifp->lq != NULLLQ)
  402.     xfree(ifp->lq);
  403.  
  404.   /* Finally free the structure itself */
  405.   xfree((char *)ifp);
  406.   return 0;
  407. }
  408.  
  409. /* Given the ascii name of an interface, return a pointer to the structure,
  410.  * or NULLIF if it doesn't exist
  411.  */
  412. struct iface *
  413. if_lookup(char *name) {
  414.   struct iface *ifp;
  415.  
  416.   for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  417.     if(strcmp(ifp->name,name) == 0)
  418.       return ifp;
  419.   return NULLIF;
  420. }
  421.  
  422. /* Return iface pointer if 'addr' belongs to one of our interfaces,
  423.  * NULLIF otherwise.
  424.  * This is used to tell if an incoming IP datagram is for us, or if it
  425.  * has to be routed.
  426.  */
  427. struct iface *
  428. ismyaddr(int32 addr) {
  429.   struct iface *ifp;
  430.  
  431.   for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  432.     if(addr == ifp->addr)
  433.       return ifp;
  434.   return NULLIF;
  435. }
  436.  
  437. /* return buffer with name + comment */
  438. char *
  439. if_name(struct iface *ifp,char *comment) {
  440.   char *result = mxallocw(strlen(ifp->name) + strlen(comment) + 2);
  441.  
  442.   sprintf(result,"%s%s",ifp->name,comment);
  443.   return result;
  444. }
  445.  
  446. #ifdef ASY
  447. /* Raw output routine that tosses all packets. Used by dialer, tip, etc */
  448. int
  449. bitbucket(struct iface *ifp,struct mbuf *bp) {
  450.   free_p(bp);
  451.   return 0;
  452. }
  453. #endif
  454.  
  455. /* Set interface parameters */
  456. int
  457. doifconfig(int argc,char *argv[],void *p) {
  458.   struct iface *ifp;
  459.   int i;
  460.  
  461.   struct cmds Ifcmds[] = {
  462.     "broadcast",    ifbroad,    0,    2,    NULLCHAR,
  463. #ifdef CRCSET
  464.     "crc",              ifcrc,          0,      2,      NULLCHAR,
  465. #endif
  466.     "encapsulation",    ifencap,    0,    2,    NULLCHAR,
  467.     "forward",        ifforw,        0,    2,    NULLCHAR,
  468.     "ipaddress",    ifipaddr,    0,    2,    NULLCHAR,
  469.     "linkaddress",    iflinkadr,    0,    2,    NULLCHAR,
  470.     "mtu",        ifmtu,        0,    2,    NULLCHAR,
  471.     "name",        ifname,        0,      2,    NULLCHAR,
  472.     "netmask",        ifnetmsk,    0,    2,    NULLCHAR,
  473.     NULLCHAR,
  474.   };
  475.  
  476.   if(argc < 2){
  477.     for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next)
  478.       showiface(ifp);
  479.     return 0;
  480.   }
  481.   if((ifp = if_lookup(argv[1])) == NULLIF){
  482.     tprintf(Badif,argv[1]);
  483.     return -1;
  484.   }
  485.   if(argc == 2){
  486.     showiface(ifp);
  487.     if ( ifp->status != NULLFP ) {
  488.       (*ifp->status)(ifp);
  489.     }
  490.     return 0;
  491.   }
  492.   if(argc == 3){
  493.     tputs("Argument missing\n");
  494.     return -1;
  495.   }
  496.   for(i=2;i<argc-1;i+=2)
  497.     subcmd(Ifcmds,3,&argv[i-1],ifp);
  498.  
  499.   return 0;
  500. }
  501.  
  502.